package br.ufpe.cin.ip.biblioteca.repositorios;

import br.ufpe.cin.ip.biblioteca.entidades.Livro;
import br.ufpe.cin.ip.biblioteca.entidades.Publicacao;
import br.ufpe.cin.ip.biblioteca.entidades.Revista;
import br.ufpe.cin.ip.biblioteca.excecoes.PublicacaoJaCadastradaException;
import br.ufpe.cin.ip.biblioteca.excecoes.PublicacaoNaoEncontradaException;
import br.ufpe.cin.ip.biblioteca.excecoes.RepositorioException;
import br.ufpe.cin.ip.biblioteca.iterator.IteratorPublicacao;
import br.ufpe.cin.ip.biblioteca.iterator.IteratorPublicacaoArray;

public class RepositorioPublicacaoArray implements RepositorioPublicacao {
	private Publicacao[] publicacoes;
	private int indice;
	
	public RepositorioPublicacaoArray() {
		super();
		this.publicacoes = new Publicacao[0];
		this.indice = 0;
	}
	
	@Override
	public void adicionar(Publicacao publicacao) throws RepositorioException, PublicacaoJaCadastradaException {
		publicacao.setId(this.indice + 1);
		
		if(this.existe(publicacao)) {
			throw new PublicacaoJaCadastradaException();
		} else {
			Publicacao[] novoArray = new Publicacao[this.publicacoes.length + 1];
			
			for(int i=0; i<this.publicacoes.length; i++) {
				novoArray[i] = this.publicacoes[i];
			}
			
			novoArray[novoArray.length-1] = publicacao;
			this.publicacoes = novoArray;
			this.indice++;
		}
	}
	
	@Override
	public void remover(Publicacao publicacao) throws RepositorioException, PublicacaoNaoEncontradaException {
		int indiceRemover = -1;
		for(int i=0; i<this.publicacoes.length; i++) {
			if(this.publicacoes[i]!=null && this.publicacoes[i].equals(publicacao))
				indiceRemover = i;
		}
		
		if(indiceRemover>=0) {
			Publicacao[] novoArray = new Publicacao[this.publicacoes.length - 1];
			
			for(int i=0; i<this.publicacoes.length; i++) {
				if(i<indiceRemover) {
					novoArray[i] = this.publicacoes[i];
				} else if(i>indiceRemover) {
					novoArray[i-1] = this.publicacoes[i];
				}
			}
			
			this.publicacoes = novoArray;
		} else {
			throw new PublicacaoNaoEncontradaException();
		}
	}
	
	@Override
	public void atualizar(Publicacao publicacao) throws RepositorioException, PublicacaoNaoEncontradaException {
		Publicacao retorno = null;
		
		for(Publicacao p : this.publicacoes) {
			if(publicacoes.equals(p))
				retorno = p;
		}
		
		if(retorno==null) {
			throw new PublicacaoNaoEncontradaException();
		} else {
			retorno.setTitulo(publicacao.getTitulo());
			retorno.setLocal(publicacao.getLocal());
			retorno.setMatriculaUsuarioEmprestimo(publicacao.getMatriculaUsuarioEmprestimo());
			
			if(retorno instanceof Livro && publicacao instanceof Livro) {
				Livro publicacaoLivro = (Livro) publicacao;
				Livro retornoLivro = (Livro) retorno;
				
				retornoLivro.setEdicao(publicacaoLivro.getEdicao());
				retornoLivro.setEditora(publicacaoLivro.getEditora());
				retornoLivro.setAnoEdicao(publicacaoLivro.getAnoEdicao());
				retornoLivro.setAnoPublicacao(publicacaoLivro.getAnoPublicacao());
			} else if(retorno instanceof Revista && publicacao instanceof Revista) {
				Revista publicacaoRevista = (Revista) publicacao;
				Revista retornoRevista = (Revista) retorno;
				
				retornoRevista.setVolume(publicacaoRevista.getVolume());
				retornoRevista.setFasciculo(publicacaoRevista.getFasciculo());
				retornoRevista.setNumero(publicacaoRevista.getNumero());
				retornoRevista.setAno(publicacaoRevista.getAno());
			}
		}
	}
	
	@Override
	public Publicacao buscar(Publicacao publicacao) throws RepositorioException, PublicacaoNaoEncontradaException {
		Publicacao retorno = null;
		
		for(Publicacao p : this.publicacoes) {
			if(publicacao.equals(p))
				retorno = p;
		}
		
		if(retorno==null) {
			throw new PublicacaoNaoEncontradaException();
		} else {
			return retorno;
		}
	}
	
	@Override
	public IteratorPublicacao getIterator() {
		return new IteratorPublicacaoArray(this.publicacoes);
	}
	
	@Override
	public boolean existe(Publicacao publicacao) throws RepositorioException {
		boolean retorno = false;
		
		for(Publicacao p : this.publicacoes) {
			if(publicacao.equals(p))
				retorno = true;
		}
		
		return retorno;
	}
}
